﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Relocation.Com;
using System.ComponentModel;
using Relocation.Com.Tools;
using Relocation.Data;
using Relocation.ControlLibrary;
using System.Diagnostics;

namespace Relocation.Base.UI
{
	/// <summary>
	/// Relocation项目所有窗体的父类
	/// </summary>
	public class BaseForm : System.Windows.Forms.Form
	{
		private ErrorProvider errorProvider;
		private IContainer components;
		/// <summary>
		/// 需要验证的Control集合
		/// </summary>
		protected List<Control> ValidatorControls = new List<Control>();

		/// <summary>
		/// 需要搜索的Control集合
		/// </summary>
		protected List<Control> SearchControls = new List<Control>();

		/// <summary>
		/// 字段控件（用于重置）
		/// </summary>
		protected List<Control> FieldControls = new List<Control>();

		/// <summary>
		/// 需要设置权限的控件
		/// </summary>
		protected List<Control> RoleControls = new List<Control>();

		/// <summary>
		/// 字段的值是否改变
		/// </summary>
		public bool FieldIsChanged
		{
			get;
			set;
		}

		public BaseForm()
		{
			InitializeComponent();
			this.Log = log4net.LogManager.GetLogger(this.GetType());
			InitControls(this.Controls); 
			this.FormClosing += new FormClosingEventHandler(this.FormClosingEvent);
		}

		public BaseForm(Session session)
			: this()
		{
			this.Session = session;			
		}

		/// <summary>
		/// 窗体初始化
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BaseForm));
			this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
			((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
			this.SuspendLayout();
			// 
			// errorProvider
			// 
			this.errorProvider.ContainerControl = this;
			// 
			// RelocationBase
			// 
			this.ClientSize = new System.Drawing.Size(292, 273);
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.Name = "BaseForm";
			this.Load += new System.EventHandler(this.RelocationBase_Load);
			((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
			this.ResumeLayout(false);
		}

		/// <summary>
		/// 日志对象
		/// </summary>
		public log4net.ILog Log
		{
			get;
			private set;
		}

		/// <summary>
		/// Session 对象
		/// </summary>
		public Session Session
		{
			get;
			set;
		}



		#region 以统一的方式显示信息
		/// <summary>
		/// 显示普通消息
		/// </summary>
		/// <param name="str">消息内容</param>
		/// <returns>DialogResult</returns>
		public virtual DialogResult MessageBoxShowInfo(string str)
		{
			return MessageBox.Show(str, "房屋拆迁安置管理系统", MessageBoxButtons.OK, MessageBoxIcon.Information);
		}

		/// <summary>
		/// 显示确认对话框
		/// </summary>
		/// <param name="message">消息内容</param>
		/// <returns>yes或no按钮</returns>
		public virtual DialogResult MessageBoxConfirm(string message)
		{
			return MessageBox.Show(message, "房屋拆迁安置管理系统", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
		}

		/// <summary>
		/// 显示错误消息
		/// </summary>
		/// <param name="message">消息内容</param>
		/// <returns>DialogResult</returns>
		public virtual DialogResult MessageBoxError(string message)
		{
			return MessageBox.Show("系统发现错误，请联系管理人员。\n" + message, "房屋拆迁安置管理系统", MessageBoxButtons.OK, MessageBoxIcon.Error);
		}

		/// <summary>
		/// 显示错误消息
		/// </summary>
		/// <param name="message">消息内容</param>
		/// <returns>DialogResult</returns>
		public virtual DialogResult MessageBoxError(Exception exception)
		{
			string message = "";
			if (exception.InnerException != null)
			{
				message = exception.InnerException.Message;
			} else
			{
				message = exception.Message;
			}
			return MessageBox.Show("系统发现错误，请联系管理人员。\n" + message, "房屋拆迁安置管理系统", MessageBoxButtons.OK, MessageBoxIcon.Error);
		}
		#endregion



		#region 统一验证、搜索、赋值、取值、权限
		protected void RelocationBase_Load(object sender, EventArgs e)
		{
			if (this.DesignMode)
				return;
			InitControls(this.Controls);
			this.InitControlsRole();

		}

		/// <summary>
		/// 遍历窗体内的所有控件，初始化验证（递归）
		/// </summary>
		protected void InitControls(Control.ControlCollection controls)
		{
			foreach (Control control in controls)
			{
				InitControl(control);
				if (control.Controls.Count > 0)
					InitControls(control.Controls);
			}
		}

		protected void InitMenuStrip(ToolStripItemCollection itemCollection)
		{
			if (itemCollection == null)
				return;
			ControlTag controlTag=null;

			try
			{
				ToolStripMenuItem item = null;
				for (int i = 0; i < itemCollection.Count; i++)
				{
					item = itemCollection[i] as ToolStripMenuItem;
					if (item != null)
					{
						controlTag = item.Tag as ControlTag;
						if (controlTag != null && controlTag.RoleInfo != null)
						{
							this.InitControlRole(item, controlTag.RoleInfo, this.Session.User);
						}
						if (item.DropDownItems.Count > 0)
						{
							InitMenuStrip(item.DropDownItems);
						}
					}
				}
					
			}
			catch (Exception ex)
			{
				this.Log.Error(ex.GetInnerExceptionMessage());
				throw;				
			}
		}
		


		/// <summary>
		/// 根据每个Control的Tag属性初始化
		/// </summary>		
		private void InitControl(Control control)
		{
			ControlTag controlTag = control.Tag as ControlTag;
			if (controlTag == null)
				return;

			if (controlTag.ValidatorInfo != null)
			{
				ValidatorControls.Add(control);
				InitControlValidator(control, controlTag.ValidatorInfo);	//绑定验证的相关事件
			}

			//绑定搜索控件
			if (controlTag.SearchInfo != null)
			{
				SearchControls.Add(control);
			}

			//绑定字段空间
			if (!String.IsNullOrEmpty(controlTag.FieldName))
			{
				FieldControls.Add(control);
				control.TextChanged += new EventHandler(FieldTextChangeEvent);
			}

			//设置权限信息
			if (controlTag.RoleInfo != null)
			{
				RoleControls.Add(control);
				InitControlRole(control, controlTag.RoleInfo, this.Session == null ? null : this.Session.User);

			}
		}


		/// <summary>
		/// 字段内容改变时发生
		/// </summary>		
		protected virtual void FieldTextChangeEvent(object sender, EventArgs e)
		{
			this.FieldIsChanged = true;
		}

		/// <summary>
		/// 窗体关闭时提示用户保存信息
		/// </summary>		
		protected virtual void FormClosingEvent(object sender, FormClosingEventArgs e)
		{
			if (this.FieldIsChanged)
			{
				if (MyMessagebox.Confirm("数据尚未保存，是否关闭？") != DialogResult.Yes)
				{
					e.Cancel = true;
				} else
				{
					this.Dispose();
				}
			}
		}
		
		#region 控件角色权限

		/// <summary>
		/// 根据权限禁用指定控件
		/// </summary>
		/// <param name="control"></param>
		protected virtual void InitControlRole(Control control, RoleInfo roleInfo, User user)
		{			
			control.Enabled = CheckRole(roleInfo, user);
		}

		/// <summary>
		/// 根据权限禁用指定控件
		/// </summary>
		/// <param name="control"></param>
		protected virtual void InitControlRole(ToolStripMenuItem control, RoleInfo roleInfo, User user)
		{
			control.Enabled = CheckRole(roleInfo, user);
		}

		private bool CheckRole(RoleInfo roleInfo, User user)
		{
			if (roleInfo == null||user == null || String.IsNullOrEmpty(user.role))
				return false;			
			return roleInfo.ShowInRoles.Any(t => t.Equals(user.role));
			
		}

		protected virtual void InitControlsRole(List<Control> controls, User user)
		{
			foreach (Control control in controls)
			{
				ControlTag tag = control.Tag as ControlTag;
				if (tag != null && tag.RoleInfo != null)
				{
					InitControlRole(control, tag.RoleInfo, user);
				}
			}
		}

		public virtual void InitControlsRole()
		{
			this.InitControlsRole(this.RoleControls, this.Session==null?null:this.Session.User);
			this.InitMenuStrip(this.MainMenuStrip==null?null:this.MainMenuStrip.Items);
		}
		#endregion


		#region 控件验证


		/// <summary>
		/// 绑定控件的验证信息
		/// </summary>
		/// <param name="control"></param>
		/// <param name="validatorInfo"></param>
		private void InitControlValidator(Control control, ValidatorInfo validatorInfo)
		{
			if (control == null || validatorInfo == null)
				return;
			control.Validating += new System.ComponentModel.CancelEventHandler(ControlValidatorEvent);

		}

		private void ControlValidatorEvent(object sender, CancelEventArgs e)
		{
			ValidatorControl(sender as Control, e);
		}

		private bool ValidatorControl(Control contorl, CancelEventArgs e)
		{
			try
			{
				if (contorl == null)
					return true;
				if (contorl.CausesValidation == false)
					return true;
				ControlTag controlTag = contorl.Tag as ControlTag;
				if (controlTag == null)
					return true;
				ValidatorInfo validatorInfo = controlTag.ValidatorInfo;
				//如果内容非必填，并且继承自ITextBoxExpend(说明用户输入的文本符合格式要求)
				//if (validatorInfo == null || (!validatorInfo.IsRequired && validatorInfo.Validator == null && contorl is IControlExpend))
				if (validatorInfo == null )
					return true;

				Relocation.Com.ValidatorInfo.ValidatorResult validatorResult = null;
				if (contorl is IControlExpend)
				{
					validatorResult=ValidatorControl_ITextBoxExpend(contorl as IControlExpend, validatorInfo);
				}
				else
				{
					validatorResult = ValidatorControl_Control(contorl, validatorInfo);
				}
				
				return ShowControlErr(contorl, validatorResult);
			} catch (Exception ex)
			{
				Debug.WriteLine(ex);
				Log.Error(ex);
				return ShowControlErr(contorl, new Relocation.Com.ValidatorInfo.ValidatorResult(true));
			}
		}

		private ValidatorInfo.ValidatorResult ValidatorControl_Control(Control contorl, ValidatorInfo validatorInfo)
		{
			try
			{
				if (validatorInfo.Validator != null)
				{
					//使用自定义的方法进行验证
					return validatorInfo.Validator(contorl);
				} else
				{
					String value = contorl.Text;

					if (!String.IsNullOrEmpty(validatorInfo.RuleString))
					{
						if (!Validator.rule(value, validatorInfo.RuleString))
						{
							return new Relocation.Com.ValidatorInfo.ValidatorResult(false, validatorInfo.RuleErrorString);
						}
					} else if (validatorInfo.IsRequired && String.IsNullOrEmpty(value))
					{
						//validatorResult = new Relocation.Com.ValidatorInfo.ValidatorResult(false, "必须填写");

						//如果此项为数字或者整数，而且又不是必填时，当用户没有输入时，自动用0填充
						if (ValidatorInfo.ValidatorTypes.Digit.Equals(validatorInfo.ValidatorType) || ValidatorInfo.ValidatorTypes.Number.Equals(validatorInfo.ValidatorType))
						{
							contorl.Text = "0";
							return new ValidatorInfo.ValidatorResult(true);

						} else
						{
							return new Relocation.Com.ValidatorInfo.ValidatorResult(false, "必须填写");
						}

					} else
					{
						switch (validatorInfo.ValidatorType)
						{
							case Relocation.Com.ValidatorInfo.ValidatorTypes.String:
								if (validatorInfo.MinLength != validatorInfo.MaxLength && validatorInfo.MaxLength != 0)
								{
									if (!Validator.length(value, validatorInfo.MinLength, validatorInfo.MinLength))
									{
										String errorStr = "长度应该在" + validatorInfo.MinLength.ToString() + "到" + validatorInfo.MaxLength.ToString() + "之间";
										return new Relocation.Com.ValidatorInfo.ValidatorResult(false, errorStr);
									}
								}
								break;
							case Relocation.Com.ValidatorInfo.ValidatorTypes.Number:
								if (!Validator.Num(value))
								{
									return new Relocation.Com.ValidatorInfo.ValidatorResult(false, "只能填写整数");
								}
								break;
							case Relocation.Com.ValidatorInfo.ValidatorTypes.Digit:
								if (!Validator.Digit(value))
								{
									return new Relocation.Com.ValidatorInfo.ValidatorResult(false, "只能填写数字");
								}
								break;
							case Relocation.Com.ValidatorInfo.ValidatorTypes.DateTime:
								if (!Validator.Datetime(value))
								{
									return new Relocation.Com.ValidatorInfo.ValidatorResult(false, "只能填写日期");
								}
								break;
							case Relocation.Com.ValidatorInfo.ValidatorTypes.Idcards:
								if (!Validator.CheckCid(value))
								{
									return new Relocation.Com.ValidatorInfo.ValidatorResult(false, "请填写正确的身份证号");
								}
								break;
							case Relocation.Com.ValidatorInfo.ValidatorTypes.Idcard15:
								if (!Validator.Idcard15(value))
								{
									return new Relocation.Com.ValidatorInfo.ValidatorResult(false, "请填写正确的身份证号");
								}
								break;
							case Relocation.Com.ValidatorInfo.ValidatorTypes.Idcard18:
								if (!Validator.Idcard18(value))
								{
									return new Relocation.Com.ValidatorInfo.ValidatorResult(false, "请填写正确的身份证号");
								}
								break;
						}
					}
				}
			} catch (Exception ex)
			{
				Debug.WriteLine(ex);
				this.Log.Error(ex.GetInnerExceptionMessage());				
			}
			return new Relocation.Com.ValidatorInfo.ValidatorResult(true);
		}

		/// <summary>
		/// 验证扩展的文本框控件
		/// </summary>
		/// <param name="contorl"></param>
		/// <param name="validatorInfo"></param>
		/// <returns></returns>
		private ValidatorInfo.ValidatorResult ValidatorControl_ITextBoxExpend(IControlExpend contorl, ValidatorInfo validatorInfo)
		{
			try
			{
				if (contorl == null || validatorInfo == null)
					return new ValidatorInfo.ValidatorResult(true);
				if (validatorInfo.IsRequired&&contorl.GetValue() == null)
				{
					return new Relocation.Com.ValidatorInfo.ValidatorResult(false, "必须填写");
				} else if (validatorInfo.Validator != null)
				{
					return validatorInfo.Validator(contorl as Control);
				}
			} catch (Exception ex)
			{
				Debug.WriteLine(ex);
				Log.Error(ex);
			}
			return new Relocation.Com.ValidatorInfo.ValidatorResult(true);
		}

		/// <summary>
		/// 显示错误信息
		/// </summary>
		/// <param name="contorl"></param>
		/// <param name="validatorResult"></param>
		protected virtual bool ShowControlErr(Control contorl, ValidatorInfo.ValidatorResult validatorResult)
		{
			if (validatorResult == null || validatorResult.Success)
			{
				this.errorProvider.SetError(contorl, "");
				return true;
			} else
			{
				this.errorProvider.SetError(contorl, validatorResult.ErrorMessage);
				return false;
			}

		}

		/// <summary>
		/// 返回错误信息提示控件
		/// </summary>
		/// <returns></returns>
		public ErrorProvider GetErrorProvider()
		{
			return this.errorProvider;
		}

		/// <summary>
		/// 验证所有需要验证的控件，并返回验证结果
		/// </summary>
		protected bool ValidatorAllControls()
		{
			if (ValidatorControls == null)
				return true;
			bool result = true;
			//遍历所有需要验证的控件
			foreach (Control control in ValidatorControls)
			{
				if (!ValidatorControl(control, null))
				{
					result = false;
				}
			}
			return result;
		}

		#endregion


		#region 控件搜索
		/// <summary>
		/// 返回搜索字符串
		/// </summary>
		/// <returns></returns>
		protected virtual string GetSearchString()
		{
			StringBuilder queryString = new StringBuilder();
			foreach (Control control in SearchControls)
			{
				ControlTag controlTag = control.Tag as ControlTag;
				if (controlTag == null||controlTag.SearchInfo == null)					
					continue;

				String value = control.Text.Trim();

				if (controlTag.SearchInfo.Rander != null)
					value = controlTag.SearchInfo.Rander(control);

				if (string.IsNullOrEmpty(value))
					continue;

				String fieldName = controlTag.SearchInfo.SearchField;
				switch (controlTag.SearchInfo.SearchFieldType)
				{
					case SearchInfo.SearchFieldTypes.String://模糊匹配
						queryString.Append(" and");
						queryString.Append(" it." + fieldName);
						queryString.Append(" like '%" + value.ToString().Replace("'", "''") + "%'");
						break;
                    case SearchInfo.SearchFieldTypes.LeftString://从左匹配
                        queryString.Append(" and");
                        queryString.Append(" it." + fieldName);
                        queryString.Append(" like '" + value.ToString().Replace("'", "''") + "%'");
                        break;
                    case SearchInfo.SearchFieldTypes.RightString://从右匹配
                        queryString.Append(" and");
                        queryString.Append(" it." + fieldName);
                        queryString.Append(" like '%" + value.ToString().Replace("'", "''") + "'");
                        break;
					case SearchInfo.SearchFieldTypes.Number:
						queryString.Append(" and");
						queryString.Append(" it." + fieldName);
						queryString.Append("=");
						queryString.Append(value);
						break;
					case SearchInfo.SearchFieldTypes.DateTime:
						queryString.Append(" and");
						DateTime dateValue = Convert.ToDateTime(value);
						queryString.Append(" Year(it." + fieldName + ")=" + dateValue.Year + " and Month(it." + fieldName + ")=" + dateValue.Month + " and Day(it." + fieldName + ")=" + dateValue.Day);
						break;

				}
			}
			if (queryString.Length > 4)
				queryString.Remove(0, 4);
			return queryString.ToString();
		}

		/// <summary>
		/// 重置搜索条件
		/// </summary>
		protected virtual void ResetSearchControls()
		{
			try
			{
				foreach (Control control in this.SearchControls)
				{
					ControlTag tag = control.Tag as ControlTag;
					if (tag == null)
						return;
					if (tag.SearchInfo == null)
						return;
					if (tag.SearchInfo.Reseter != null)
						tag.SearchInfo.Reseter(control);
					else
						control.Text = string.Empty;
				}
			} catch (Exception ex)
			{				
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				throw;
			}
		}

		#endregion

		/// <summary>
		/// 清空所有字段内容
		/// </summary>
		protected virtual void ResetFields()
		{
			if (this.FieldControls == null)
				return;
			foreach (Control control in FieldControls)
			{
				this.ResetField(control);
			}
		}

		/// <summary>
		/// 清空字段的输入（可重写）
		/// </summary>		
		protected virtual void ResetField(Control control)
		{
			control.Text = string.Empty;
		}

		/// <summary>
		/// 通过反射以及对控件Tag属性的配置，获取用户的输入赋值到实体
		/// </summary>
		/// <param name="tagEntity"></param>
		protected virtual void GetValueFromInput(Object entity)
		{
			try
			{
				foreach (Control control in FieldControls)
				{
					ControlTag controlTag = control.Tag as ControlTag;
					if (controlTag == null)
						continue;
					if (string.IsNullOrEmpty(controlTag.FieldName))
						continue;
					IControlExpend iTextBoxExpend = control as IControlExpend;
					object p_value = iTextBoxExpend == null ? control.Text : iTextBoxExpend.GetValue();
					Type p_type = Reflector.GetNotNullType(Reflector.GetPropertyInfo(entity, controlTag.FieldName).PropertyType);

					if (typeof(decimal).Equals(p_type) || typeof(int).Equals(p_type))
					{
						Reflector.SetPropertyValue(entity, controlTag.FieldName, p_value == null ? "0" : p_value);
					} else if (typeof(DateTime).Equals(p_type))
					{
						Reflector.SetPropertyValue(entity, controlTag.FieldName, p_value == null ? null : p_value);
					} else
						Reflector.SetPropertyValue(entity, controlTag.FieldName, control.Text);
				}
				return;
			} catch (Exception ex)
			{				
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				throw;
			}
		}


		/// <summary>
		/// 通过反射以及对控件Tag属性的配置，自动填充文本框
		/// </summary>
		/// <param name="tagEntity"></param>
		protected virtual void SetValueToInput(object entity)			
		{
			try
			{
				if (FieldControls.Count < 1)
				{
					this.InitControls(this.Controls);
				}
				foreach (Control control in FieldControls)
				{
					ControlTag controlTag = control.Tag as ControlTag;
					if (controlTag == null)
						continue;
					if (string.IsNullOrEmpty(controlTag.FieldName))
						continue;

					Object p_value = Reflector.GetPropertyValue(entity, controlTag.FieldName);
					Type p_type = Reflector.GetNotNullType(Reflector.GetPropertyInfo(entity, controlTag.FieldName).PropertyType);

					IControlExpend iTextBoxExpend = control as IControlExpend;
					if (iTextBoxExpend != null)
					{
						iTextBoxExpend.SetValue(p_value);
					} else if (typeof(decimal).Equals(p_type))
					{
						control.Text = p_value == null ? "0.00" : Convert.ToDecimal(p_value).ToString("n2").Replace(",", "");
					} else
					{
						control.Text = p_value == null ? string.Empty : p_value.ToString();
					}
				}
				this.FieldIsChanged = false;
			} catch (Exception ex)
			{	
				Log.Error(ex.GetInnerExceptionMessage());
				System.Diagnostics.Debug.WriteLine(ex);
				throw;
			}
		}
		#endregion


		/// <summary>
		/// 在拥有此控件的基础窗口句柄的线程上执行指定的委托。（如果当前控件没有创建，则直接执行）
		/// </summary>
		/// <param name="methodInvoker"></param>
		public virtual void ExecMethodInvoker(MethodInvoker methodInvoker)
		{
			if (methodInvoker == null)
				return;
			if (this.Created)
				this.Invoke(methodInvoker);
			else
				methodInvoker();
		}	

	}



}
